package com.m4f.city.business.service.impl;

import java.util.Calendar;
import java.util.logging.Logger;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.m4f.city.business.oauth2.ifc.OAuth2TokensService;
import com.m4f.city.business.service.ifc.ApiService;
import com.m4f.city.business.service.ifc.ApplicationService;
import com.m4f.city.business.service.ifc.CompanyService;
import com.m4f.city.business.service.ifc.IServiceLocator;
import com.m4f.city.business.service.ifc.OrganizationService;
import com.m4f.city.business.service.ifc.UserService;
import com.m4f.gaeweb.business.service.exception.ContextNotActiveException;
import com.m4f.gaeweb.business.service.exception.ServiceNotFoundException;


public class SpringServiceLocator implements IServiceLocator, ApplicationContextAware {
	
	private static final Logger LOGGER = Logger.getLogger(SpringServiceLocator.class.getName());
	private ApplicationContext ctx;
	private ClassPathXmlApplicationContext servicesCtx;
	
	@Override
	public void setApplicationContext(ApplicationContext appCtx)
			throws BeansException {
		this.ctx = appCtx;
		this.servicesCtx = (ClassPathXmlApplicationContext) this.ctx.getBean("servicesContext");
	}
	
	public void init() {
		long init = Calendar.getInstance().getTimeInMillis();
		LOGGER.severe("---Starting init Service Locator Bean " );
		this.servicesCtx.setConfigLocation("services-config.xml");
		this.servicesCtx.stop();
		this.servicesCtx.refresh();
		this.servicesCtx.start();
		long end = Calendar.getInstance().getTimeInMillis();
		LOGGER.severe("---Ending init Service Locator Bean, elapsed time " + 
				((end-init)/1000) );
    }
	
	@Override
	public UserService getUserService() throws ServiceNotFoundException, ContextNotActiveException {
		return this.getService(UserService.class);
	}
	
	@Override
	public ApiService getApiService() throws ServiceNotFoundException, ContextNotActiveException {
		return this.getService(ApiService.class);
	}
	
	@Override
	public ApplicationService getApplicationService() throws ServiceNotFoundException, ContextNotActiveException {
		return this.getService(ApplicationService.class);
	}
	
	@Override
	public OAuth2TokensService getOAuth2TokensService() throws ServiceNotFoundException, ContextNotActiveException {
		return this.getService(OAuth2TokensService.class);
	}
	
	@Override
	public OrganizationService getOrganizationService() throws ServiceNotFoundException, ContextNotActiveException {
		return this.getService(OrganizationService.class);
	}
	
	@Override
	public CompanyService getCompanyService() throws ServiceNotFoundException, ContextNotActiveException {
		return this.getService(CompanyService.class);
	}
	
	private <T extends Object> T getService(Class<T> clazz) 
		throws ServiceNotFoundException, ContextNotActiveException {
		T bean = null;
		try {
			if(!this.servicesCtx.isRunning()) {
				throw new ContextNotActiveException("#### Context is not RUNNING....");
			}
			if(!this.servicesCtx.isActive()) {
				throw new ContextNotActiveException("#### Context is not ACTIVE....");
			}
			bean = this.servicesCtx.getBean(clazz);
		} catch(NoSuchBeanDefinitionException ex) {
			this.servicesCtx.setConfigLocation("services-config.xml");
			this.servicesCtx.stop();
			this.servicesCtx.refresh();
			this.servicesCtx.start();
			bean = this.servicesCtx.getBean(clazz);
		}
		return bean;
	}
}
